/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.schedule;

import org.zhiqim.kernel.Z;
import org.zhiqim.kernel.constants.SignConstants;
import org.zhiqim.kernel.json.Jsons;
import org.zhiqim.kernel.model.maps.MapSS;
import org.zhiqim.kernel.util.Arrays;
import org.zhiqim.kernel.util.Ints;
import org.zhiqim.kernel.util.Validates;

/**
 * 定时器工厂，用于根据参数生成指定的任务的处理器
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public class ScheduleFactory implements SignConstants
{
    /**
     * 通过参数值，创建系统默认的任务处理器
     * 
     * @param taskClassName 任务类名
     * @param taskValue     任务参数值
     * @return              TaskThreader
     */
    public static Object getTaskThreader(String taskClassName, String taskValue)
    {
        if (Validates.isEmpty(taskClassName) || Validates.isEmpty(taskValue))
            return null;
        
        //1.判断任务是不是有效的
        Object task =  Z.cls().newInstance(taskClassName);
        if (task == null || !(task instanceof Task))
            return null;
        
        //2.判断参数值是不是两个或三个，格式为{name:Month, time:1/0/0/0}或{name:Month, time:1/0/0/0, first:true},{name:Interval, time:3, first:true}
        MapSS paramMap = Jsons.toMapSS(taskValue);
        String name = paramMap.get(_NAME_);
        if (Validates.isEmptyBlank(name))
            return null;
        
        if (_INTERVAL_.equals(name))
        {//检查到是Interval时返回Interval
            return getTaskInterval((Task)task, paramMap);
        }
        else
        {//否则返回TaskThreader
            return getTaskThreader((Task)task, paramMap);
        }
    }
    
    /**
     * 通过参数值，创建系统默认的任务处理器
     * 
     * @param task      任务
     * @param param     参数字符串，如{name:Month, time:1/0/0/0, first:true}
     * @return          TaskThreader
     */
    public static TaskThreader getTaskThreader(Task task, String param)
    {
        MapSS paramMap = Jsons.toMapSS(param);
        if (!paramMap.containsKey(_NAME_) || !paramMap.containsKey("time"))
            return null;
        
        return getTaskThreader(task, paramMap);
    }
    
    /**
     * 通过参数值，创建系统默认的任务处理器
     * 
     * @param task      任务
     * @param param     参数数组
     * @return          TaskThreader
     */
    public static TaskThreader getTaskThreader(Task task, MapSS paramMap)
    {
        String name = paramMap.get(_NAME_);
        String time = paramMap.get("time");
        String first = paramMap.get("first");
        
        int[] timeArr = Arrays.toIntArray(time, "/");
        boolean isFirst = (first == null)?false:(_TRUE_.equals(first));
        
        //3.3检查任务处理器
        Object obj = Z.cls().newInstance(name);
        if (obj == null || !(obj instanceof TaskThreader))
            return null;
        
        //3.4把参数设置好并安排
        TaskThreader threader = (TaskThreader)obj;
        if (isFirst){
            threader.setFirstPreviousExecute();
        }
        
        return threader.schedule((Task)task, timeArr);
    }
    
    /**
     * 获取任务Interval，支持参数配置{name:Interval, time:3, first:true}，默认first:false
     * first:true表示第一次立即执行，以后每次等3秒
     * first:false表示每次等3秒，以后每次等3秒
     * 
     * @param task      任务
     * @param param     参数
     * @return          返回null，表示不放置到scheduler中
     */
    public static Interval getTaskInterval(Task task, MapSS paramMap)
    {
        String time = paramMap.get("time");
        String first = paramMap.get("first");
        
        if (!Validates.isIntegerValue(time, 1, Integer.MAX_VALUE))
            return null;//小于1大于整型最大值
        
        boolean isFirst = (first == null)?false:(_TRUE_.equals(first));
        int middleMillis = Ints.toInt(time) * 1000;
        int firstMillis = isFirst?0:middleMillis;
        
        return Interval.shedule(task, firstMillis, middleMillis);
    }
}
